import Foundation
import CoreLocation

class AMapService {
    static let shared = AMapService()
    
    private var apiKey: String {
        return GeocodingConfig.shared.amapApiKey
    }
    
    private let baseURL = "https://restapi.amap.com/v3"
    private let timeoutInterval: TimeInterval = 15.0
    
    private init() {}
    
    // MARK: - 逆向地理编码（坐标转地址）
    func reverseGeocode(coordinate: CLLocationCoordinate2D) async -> GlobalLocationAddressInfo? {
        let urlString = "\(baseURL)/geocode/regeo?key=\(apiKey)&location=\(coordinate.longitude),\(coordinate.latitude)&output=json&extensions=all"
        
        guard let url = URL(string: urlString) else {
            print("🗺️ [AMap] 无效URL: \(urlString)")
            return nil
        }
        
        var request = URLRequest(url: url)
        request.timeoutInterval = timeoutInterval
        
        do {
            let (data, response) = try await URLSession.shared.data(for: request)
            
            guard let httpResponse = response as? HTTPURLResponse else {
                print("🗺️ [AMap] 无效HTTP响应")
                return nil
            }
            
            print("🗺️ [AMap] 逆向地理编码响应状态: \(httpResponse.statusCode)")
            
            if httpResponse.statusCode == 200 {
                let result = try JSONDecoder().decode(AMapGeocodeResponse.self, from: data)
                
                if result.status == "1" && result.info == "OK" {
                    guard let regeocode = result.regeocode else {
                        print("🗺️ [AMap] 逆向地理编码失败: 无地址信息")
                        return nil
                    }
                    
                    let addressComponent = regeocode.addressComponent
                    let formattedAddress = regeocode.formattedAddress.value
                    
                    let addressInfo = GlobalLocationAddressInfo(
                        country: addressComponent.country,
                        province: addressComponent.province,
                        city: addressComponent.city,
                        district: addressComponent.district,
                        township: addressComponent.township,
                        street: addressComponent.street,
                        poiName: regeocode.pois?.first?.name,
                        formattedAddress: formattedAddress
                    )
                    
                    print("🗺️ [AMap] 逆向地理编码成功: \(coordinate) -> \(formattedAddress)")
                    return addressInfo
                } else {
                    print("🗺️ [AMap] 逆向地理编码失败: \(result.info)")
                }
            } else {
                print("🗺️ [AMap] HTTP错误: \(httpResponse.statusCode)")
            }
        } catch {
            print("🗺️ [AMap] 逆向地理编码异常: \(error)")
        }
        
        return nil
    }
    
    // MARK: - 正向地理编码（地址转坐标）
    func geocodeAddress(_ address: String) async -> CLLocationCoordinate2D? {
        let encodedAddress = address.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
        let urlString = "\(baseURL)/geocode/geo?key=\(apiKey)&address=\(encodedAddress)&output=json"
        
        guard let url = URL(string: urlString) else {
            print("🗺️ [AMap] 无效URL: \(urlString)")
            return nil
        }
        
        var request = URLRequest(url: url)
        request.timeoutInterval = timeoutInterval
        
        do {
            let (data, response) = try await URLSession.shared.data(for: request)
            
            guard let httpResponse = response as? HTTPURLResponse else {
                print("🗺️ [AMap] 无效HTTP响应")
                return nil
            }
            
            print("🗺️ [AMap] 正向地理编码响应状态: \(httpResponse.statusCode)")
            
            if httpResponse.statusCode == 200 {
                let result = try JSONDecoder().decode(AMapGeocodeResponse.self, from: data)
                
                if result.status == "1" && result.info == "OK" {
                    guard let geocodes = result.geocodes, !geocodes.isEmpty else {
                        print("🗺️ [AMap] 正向地理编码失败: 无结果")
                        return nil
                    }
                    
                    let geocode = geocodes[0]
                    let location = geocode.location
                    let coordinates = location.components(separatedBy: ",")
                    
                    guard coordinates.count == 2,
                          let longitude = Double(coordinates[0]),
                          let latitude = Double(coordinates[1]) else {
                        print("🗺️ [AMap] 正向地理编码失败: 无效坐标格式")
                        return nil
                    }
                    
                    let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
                    print("🗺️ [AMap] 正向地理编码成功: \(address) -> \(coordinate)")
                    return coordinate
                } else {
                    print("🗺️ [AMap] 正向地理编码失败: \(result.info)")
                }
            } else {
                print("🗺️ [AMap] HTTP错误: \(httpResponse.statusCode)")
            }
        } catch {
            print("🗺️ [AMap] 正向地理编码异常: \(error)")
        }
        
        return nil
    }
}

// MARK: - 高德地图API响应模型
struct AMapGeocodeResponse: Codable {
    let status: String
    let info: String
    let geocodes: [AMapGeocode]?
    let regeocode: AMapRegeocode?
}

struct AMapGeocode: Codable {
    let location: String
    let formattedAddress: String
    
    enum CodingKeys: String, CodingKey {
        case location
        case formattedAddress = "formatted_address"
    }
}

struct AMapRegeocode: Codable {
    let formattedAddress: StringOrArray
    let addressComponent: AMapAddressComponent
    let pois: [AMapPOI]?
    
    enum CodingKeys: String, CodingKey {
        case formattedAddress = "formatted_address"
        case addressComponent = "addressComponent"
        case pois
    }
}

// 处理可能是字符串或数组的字段
struct StringOrArray: Codable {
    let value: String
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        
        if let stringValue = try? container.decode(String.self) {
            value = stringValue
        } else if let arrayValue = try? container.decode([String].self) {
            value = arrayValue.joined(separator: ", ")
        } else {
            value = "未知地址"
        }
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(value)
    }
}

struct AMapAddressComponent: Codable {
    let country: String?
    let province: String?
    let city: String?
    let district: String?
    let township: String?
    let street: String?
    
    enum CodingKeys: String, CodingKey {
        case country
        case province
        case city
        case district
        case township
        case street
    }
}

struct AMapPOI: Codable {
    let name: String?
    let type: String?
    let address: String?
    
    enum CodingKeys: String, CodingKey {
        case name
        case type
        case address
    }
}

// MARK: - 异步扩展方法
extension AMapService {
    /// 获取地址信息（异步），用于统一接口
    func fetchAddressInfoAsync(coordinate: CLLocationCoordinate2D) async -> GlobalLocationAddressInfo? {
        print("[\(Date())] \(#function) called with coordinate: \(coordinate)")
        return await reverseGeocode(coordinate: coordinate)
    }
} 